package com.ku.log.util;

import com.ku.log.entity.Operator;
import com.ku.log.entity.SysLog;
import org.springframework.util.ClassUtils;

/**
 * @author: GZQ
 * @create: 2020/08/09
 * @description: 使用ThreadLocal来保存当前请求线程的操作参数
 **/
public class ThreadLocals {
    /**
     * 当前请求线程操作人
     */
    private static final ThreadLocal<Operator> LOCAL_OPERATOR = new ThreadLocal<>();
    /**
     * 当前线程日志
     */
    private static final ThreadLocal<SysLog> LOCAL_LOG = new ThreadLocal<>();

    @SuppressWarnings("all")
    private static <T> ThreadLocal<T> getInstance(Class<T> cls){
        //判断当前类型是否为目标类
        if (ClassUtils.isAssignable(cls, Operator.class)) {
            return (ThreadLocal<T>) LOCAL_OPERATOR;
        }
        if (ClassUtils.isAssignable(cls, SysLog.class)) {
            return (ThreadLocal<T>) LOCAL_LOG;
        }
        return null;
    }

    /**
     * @param cls 存储类型 可选 Operator.class/SysLog.class
     * @param t 要存储的对象
     * @param <T> 泛型指定
     */
    public static <T> void setLocal(Class<T> cls,T t){
        ThreadLocal<T> instance = getInstance(cls);
        if (instance != null && t != null){
            instance.set(t);
        }
    }

    /**
     * 设置本地线程变量对应对象值
     * @param t 存储类型 可选 Operator.class（操作人）/SysLog.class（操作日志）
     * @param <T> 指定泛型
     * @return  本地线程值
     */
    public static <T> T getLocal(Class<T> t){
        ThreadLocal<T> instance = getInstance(t);
        return instance == null ? null : instance.get();
    }

    /**
     * 退出登陆或session失效需调用此方法，清除本地线程中存储的当前变量（操作人信息需要使用方系统自己调用）
     * @param t 移除类型 可选 Operator.class（操作人）/SysLog.class（操作日志）
     * @param <T> 指定泛型
     */
    public static <T> void removeLocal(Class<T> t){
        ThreadLocal<T> instance = getInstance(t);
        if (instance != null && instance.get() != null){
            instance.remove();
        }
    }
}
